package ink.tiptop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.trilead.ssh2.Connection;
import ink.tiptop.persist.domain.entity.ZjfBaseServerInfoEntity;
import ink.tiptop.dto.req.base.server.*;
import ink.tiptop.enums.EResp;
import ink.tiptop.common.domain.WebworkResponse;
import ink.tiptop.dto.resp.base.ZjfBaseServerInfo;
import ink.tiptop.common.cache.CacheAble;
import ink.tiptop.common.cache.CacheEvict;
import ink.tiptop.common.cache.ECaches;
import ink.tiptop.common.cache.ICache;
import ink.tiptop.exception.JDTException;
import ink.tiptop.exception.JDTExceptionMsg;
import ink.tiptop.persist.dao.ZjfBaseServerInfoMapper;
import ink.tiptop.persist.dao.ZjfServiceRemoteViewMapper;
import ink.tiptop.common.domain.req.PageRequest;
import ink.tiptop.common.domain.rsp.Response;
import ink.tiptop.common.domain.rsp.SucceedResponse;
import ink.tiptop.service.AbstractBaseService;
import ink.tiptop.service.CacheSearch;
import ink.tiptop.utils.ParamUtils;
import ink.tiptop.utils.date.DateBaseHolder;
import ink.tiptop.utils.JSON;
import ink.tiptop.utils.ssh.SshInfo;
import ink.tiptop.utils.ssh.SshUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Observable;
import java.util.stream.Collectors;

/**
 * 服务器基本连接信息(ZjfBaseServerInfoEntity)表服务实现类
 *
 * @author makejava
 * @since 2020-06-21 20:40:28
 */
@Service("zjfBaseServerInfoService")
@Slf4j
public class ZjfBaseServerInfoServiceImpl extends AbstractBaseService<ZjfBaseServerInfoEntity> implements ink.tiptop.service.ZjfBaseServerInfoService{


    private static final String CACHE_KEY = "BASE_SERVER";
    private static final String CACHE_CLEAR = CACHE_KEY + "*";

    @Resource
    private ZjfBaseServerInfoMapper zjfBaseServerInfoMapper;
    @Autowired
    private CacheSearch<ZjfBaseServerInfoEntity> cacheSearch;
    @Autowired
    private ICache<String> cache;
    @Resource
    private ZjfServiceRemoteViewMapper serviceRemoteViewMapper;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ZjfBaseServerInfoEntity queryById(Integer id) {
        return this.zjfBaseServerInfoMapper.selectById(id);
    }

    /**
     * 查询多条数据
     *
     * @return 对象列表
     */
    @Override
    public List<ZjfBaseServerInfoEntity> queryAll() {
        String cacheKey = CACHE_KEY + "ALL";
        List<ZjfBaseServerInfoEntity> list = cacheSearch.getList(cacheKey, ZjfBaseServerInfoEntity.class, ECaches.DAY);
        if (list == null) {
            list = zjfBaseServerInfoMapper.selectList(null);
            cache.setVal(cacheKey, JSON.toJSONString(list), ECaches.DAY);
        }
        return list;
    }

    /**
     * 修改数据
     *
     * @param zjfBaseServerInfoEntity 实例对象
     * @return 实例对象
     */
    @Override
    @CacheEvict(key = CACHE_CLEAR, type = ECaches.DAY)
    public ZjfBaseServerInfoEntity update(ZjfBaseServerInfoEntity zjfBaseServerInfoEntity) {
        this.zjfBaseServerInfoMapper.updateById(zjfBaseServerInfoEntity);
        return this.queryById(zjfBaseServerInfoEntity.getId());
    }

    @Override
    @CacheEvict(key = CACHE_CLEAR, type = ECaches.DAY)
    public Response update(UpdateZjfBaseServerInfoRequest request) {
        ZjfBaseServerInfoEntity updateEntity = new ZjfBaseServerInfoEntity();
        BeanUtils.copyProperties(request, updateEntity);

        int rows = 0;
        try {
            rows = zjfBaseServerInfoMapper.updateById(updateEntity);
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                return WebworkResponse.failed(EResp.EServerInfo.ERROR_EXIST);
            }
        }
        if (rows > 0) {
            return WebworkResponse.SUCCEED;
        }
        return WebworkResponse.ERROR;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    @CacheEvict(key = CACHE_CLEAR, type = ECaches.DAY)
    public boolean deleteById(Integer id) {
        return this.zjfBaseServerInfoMapper.deleteById(id) > 0;
    }

    @Override
    @CacheEvict(key = CACHE_CLEAR, type = ECaches.DAY)
    public Response add(AddZjfBaseServerInfoRequest request) {
        // 操作员=用户名 + 版本 + ip + port 唯一
        ZjfBaseServerInfoEntity query = new ZjfBaseServerInfoEntity();
        query.setHost(request.getHost());
        query.setPort(request.getPort());
        query.setUser(request.getUser());

        int count = zjfBaseServerInfoMapper.selectCount(new QueryWrapper<>(query));
        if (count > 0) {
            return WebworkResponse.failed(EResp.EServerInfo.ERROR_EXIST);
        }

        ZjfBaseServerInfoEntity serverInfo = new ZjfBaseServerInfoEntity();
        BeanUtils.copyProperties(request, serverInfo);
        serverInfo.setCreateTime(new Date());
        int rows = zjfBaseServerInfoMapper.insert(serverInfo);
        if (rows > 0) {
            return SucceedResponse.SUCCEED;
        }
        return WebworkResponse.failed(EResp.EServerInfo.ERROR_ADD);
    }

    @Override
    @CacheAble(keyPrefix = CACHE_KEY, desc = "查询服务器基本信息列表缓存", type = ECaches.DAY)
    public Response list(QueryZjfBaseServerInfoRequest zjfBaseServerInfoEntity) {
        return super.list(zjfBaseServerInfoEntity);
    }

    @Override
    @CacheEvict(key = CACHE_CLEAR, type = ECaches.DAY)
    public Response delete(DeleteZjfBaseServerInfoRequest request) {
        // 请求删除的ID列表
        List<Integer> reqIdList = ParamUtils.toIntList(request.getId());
        // 2.查询到关联的id列表
        List<Integer> relatedIdList = getRelatedList(request.getId());
        if (relatedIdList != null && !relatedIdList.isEmpty()) {
            // 请求删除的id列表 删除 关联的id列表 , 剩下的是可以都删除的
            List<Integer> delIdList = reqIdList.stream().filter(req -> !relatedIdList.contains(req)).collect(Collectors.toList());
            if (delIdList == null || delIdList.isEmpty()) {
                return WebworkResponse.failed(EResp.EServerInfo.ERROR_DELETE_FORBID);
            }
            int rows = zjfBaseServerInfoMapper.deleteBatchIds(delIdList);
            if (rows > 0) {
                return WebworkResponse.failed(EResp.EServerInfo.ERROR_DELETE_PART);
            }
        } else {
            int count = zjfBaseServerInfoMapper.deleteBatchIds(reqIdList);
            if (count > 0) {
                return WebworkResponse.SUCCEED;
            }
        }
        return WebworkResponse.ERROR;
    }

    private List<Integer> getRelatedList(List<String> reqIdList) {
        String ids = String.join(",", reqIdList);
        // 2.查询到关联的id列表
        return serviceRemoteViewMapper.listRelatedIdList(ids);
    }

    @Override
    public void checkServerExist(Integer serverId) {
        ZjfBaseServerInfoEntity entity = new ZjfBaseServerInfoEntity();
        entity.setId(serverId);
        if (zjfBaseServerInfoMapper.selectCount(new QueryWrapper<>(entity)) == 0) {
            JDTException.throwException(JDTExceptionMsg.getError(EResp.EServerInfo.ERROR_EXIST_NOT));
        }
    }

    @Override
    protected void setOrderBy(PageRequest request) {

    }

    @Override
    protected ZjfBaseServerInfoEntity getQueryParam(PageRequest request) {
        // 如果没有特殊的值需要获取,那么就不需要强转出来了
//        QueryZjfBaseServerInfoRequest param = (QueryZjfBaseServerInfoRequest) request;
        ZjfBaseServerInfoEntity entity = new ZjfBaseServerInfoEntity();
        BeanUtils.copyProperties(request, entity);
        return entity;
    }

    @Override
    protected Page<ZjfBaseServerInfoEntity> getQueryEntityList(Page<ZjfBaseServerInfoEntity> page, ZjfBaseServerInfoEntity param) {
        return zjfBaseServerInfoMapper.selectPage(page, new QueryWrapper<>(param));
    }

    @Override
    protected Object getResponseList(List<ZjfBaseServerInfoEntity> voList) {
        ZjfBaseServerInfo responseInfo;
        List<ZjfBaseServerInfo> infos = new ArrayList<>();
        for (ZjfBaseServerInfoEntity entityInfo : voList) {
            responseInfo = new ZjfBaseServerInfo();
            BeanUtils.copyProperties(entityInfo, responseInfo);

            responseInfo.setCreateTime(ParamUtils.dateToStrPattern(entityInfo.getCreateTime(), DateBaseHolder.Pattern.Y_M_D_H_M_S));
            responseInfo.setUpdateTime(ParamUtils.dateToStrPattern(entityInfo.getUpdateTime(), DateBaseHolder.Pattern.Y_M_D_H_M_S));
            // 连接方式,0:密码,1:key
            Integer connway = entityInfo.getConnWay();
            responseInfo.setConnWay(connway);
            infos.add(responseInfo);
        }
        return infos;
    }


    // 获取连接
    @Override
    public Connection getConnection(ZjfBaseServerInfoEntity request) throws IOException {
        SshInfo sshInfo = new SshInfo(request.getHost(), request.getPort(), request.getUser(), request.getPass());
        return SshUtil.connect(sshInfo);
    }

    @Override
    public void update(Observable o, Object arg) {
        log.info("预热ZjfBaseServerInfoServiceImpl缓存");
        this.queryAll();
    }


}